package com.yonyou.cyxdms.basedata.service.service.sap;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.yonyou.cyx.framework.bean.dto.framework.RestResultResponse;
import com.yonyou.cyx.framework.bean.entity.base.BasePO;
import com.yonyou.cyx.function.exception.ServiceBizException;
import com.yonyou.cyxdms.basedata.client.domains.vo.*;
import com.yonyou.cyxdms.basedata.service.config.annotation.InterfaceLog;
import com.yonyou.cyxdms.basedata.service.constant.BasedataCommonConstants;
import com.yonyou.cyxdms.basedata.service.constant.BasedataDictConstants;
import com.yonyou.cyxdms.basedata.service.dto.sap.*;
import com.yonyou.cyxdms.basedata.service.dto.vehiclemodel.*;
import com.yonyou.cyxdms.basedata.service.entity.brand.BrandPO;
import com.yonyou.cyxdms.basedata.service.entity.color.ColorPO;
import com.yonyou.cyxdms.basedata.service.entity.configurer.PackagePO;
import com.yonyou.cyxdms.basedata.service.entity.model.ModelPO;
import com.yonyou.cyxdms.basedata.service.entity.option.VsOptionPO;
import com.yonyou.cyxdms.basedata.service.entity.product.VsProductPO;
import com.yonyou.cyxdms.basedata.service.entity.productOption.VsProductOptionPO;
import com.yonyou.cyxdms.basedata.service.entity.sap.TiSapConfigPricePO;
import com.yonyou.cyxdms.basedata.service.entity.sap.TiSapOptionPO;
import com.yonyou.cyxdms.basedata.service.entity.sap.TiSapProductPO;
import com.yonyou.cyxdms.basedata.service.entity.sap.TiSapProductRulePO;
import com.yonyou.cyxdms.basedata.service.entity.series.SeriesPO;
import com.yonyou.cyxdms.basedata.service.feign.SapProductClient;
import com.yonyou.cyxdms.basedata.service.repository.brand.BrandMapper;
import com.yonyou.cyxdms.basedata.service.repository.color.ColorMapper;
import com.yonyou.cyxdms.basedata.service.repository.configurer.PackageMapper;
import com.yonyou.cyxdms.basedata.service.repository.model.ModelMapper;
import com.yonyou.cyxdms.basedata.service.repository.option.VsOptionMapper;
import com.yonyou.cyxdms.basedata.service.repository.product.VsProductMapper;
import com.yonyou.cyxdms.basedata.service.repository.productOption.VsProductOptionMapper;
import com.yonyou.cyxdms.basedata.service.repository.sap.TiSapConfigPriceMapper;
import com.yonyou.cyxdms.basedata.service.repository.sap.TiSapOptionMapper;
import com.yonyou.cyxdms.basedata.service.repository.sap.TiSapProductMapper;
import com.yonyou.cyxdms.basedata.service.repository.sap.TiSapProductRuleMapper;
import com.yonyou.cyxdms.basedata.service.repository.series.SeriesMapper;
import com.yonyou.cyxdms.basedata.service.service.brand.BrandService;
import com.yonyou.cyxdms.basedata.service.service.color.ColorService;
import com.yonyou.cyxdms.basedata.service.service.configure.PackageService;
import com.yonyou.cyxdms.basedata.service.service.model.ModelService;
import com.yonyou.cyxdms.basedata.service.service.option.VsOptionService;
import com.yonyou.cyxdms.basedata.service.service.product.VsProductService;
import com.yonyou.cyxdms.basedata.service.service.series.SeriesService;
import com.yonyou.cyxdms.basedata.service.util.TransactionUtils;
import com.yonyou.cyxdms.basedata.service.util.ZipUtils;
import com.yonyou.cyxdms.basedata.service.vo.productprice.SaveProductPriceVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.util.Assert;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
@Transactional(rollbackFor = Exception.class)
public class SapProductServiceImpl implements SapProductService {

    private final String PLATFORM = "EV/SC02";
    private static final String INTERFACE_PRODUCT = "INTERFACE_PRODUCT";
    private static final String INTERFACE_OPTION = "INTERFACE_OPTION";

    private static final String OPTION_CODE_EXCLUDE_PRE1 = "MF";

    private static final String OPTION_SAPERATOR1 = "/";
    private static final String OPTION_SAPERATOR2 = "=";

    private static final Integer IS_HANDLE_NOT = 0;
    private static final Integer IS_HANDLE_YES = 1;

    @Autowired
    SapCxfClientService sapCxfClientService;
    @Autowired
    SapProductClient sapProductClient;
    @Autowired
    TiSapProductMapper sapProductMapper;
    @Autowired
    TiSapOptionMapper sapOptionMapper;
    @Autowired
    DealerToSapService dealerToSapService;
    @Autowired
    BrandService brandService;
    @Autowired
    SeriesService seriesService;
    @Autowired
    ModelService modelService;
    @Autowired
    PackageService packageService;
    @Autowired
    VsOptionService vsOptionService;
    @Autowired
    BrandMapper brandMapper;
    @Autowired
    SeriesMapper seriesMapper;
    @Autowired
    ModelMapper modelMapper;
    @Autowired
    PackageMapper packageMapper;
    @Autowired
    VsOptionMapper vsOptionMapper;
    @Autowired
    VsProductService vsProductService;
    @Autowired
    VsProductMapper vsProductMapper;
    @Autowired
    ColorService colorService;
    @Autowired
    ColorMapper colorMapper;
    @Autowired
    VsProductOptionMapper vsProductOptionMapper;
    @Autowired
    TiSapProductRuleMapper sapProductRuleMapper;
    @Autowired
    TiSapConfigPriceMapper sapConfigPriceMapper;

    @Autowired
    private TransactionUtils transactionUtils ;


    public SapProductInDto getProductInDto(String param){
        String startDate = LocalDate.now().minusDays(1).toString();
        String endDate = LocalDate.now().minusDays(1).toString();
        SapProductInDto sapProductInDto = null;
        if(StringUtils.isNotEmpty(param)){
            sapProductInDto = JSONObject.parseObject(param, SapProductInDto.class);
            if (StringUtils.isEmpty(sapProductInDto.getPlatForm())){
                sapProductInDto.setPlatForm(PLATFORM);
            }
            Assert.hasText(sapProductInDto.getStartDate(),"开始日期不能为空");
            Assert.hasText(sapProductInDto.getEndDate(),"结束日期不能为空");
        }else{
            sapProductInDto = new SapProductInDto();
            sapProductInDto.setPlatForm(PLATFORM);
            sapProductInDto.setStartDate(startDate);
            sapProductInDto.setEndDate(endDate);
        }
        return sapProductInDto;
    }

    @Override
    public void getProductInfo(String param) {
        SapProductInDto sapProductInDto = getProductInDto(param);
        String batchNo = UUID.randomUUID().toString();
        RestResultResponse<SapProOutDto> res = sapCxfClientService.getProductRest(batchNo, INTERFACE_PRODUCT, sapProductInDto);
        if(res == null || !res.isSuccess()){
            return;
        }
        SapProOutDto data = res.getData();
        List<SapProductOutDto> productList = data.getProductList();
        List<SapProductRuleOutDto> ruleList = data.getRuleList();
        for (SapProductOutDto sapProductOutDto : productList) {
            TiSapProductPO productPO = new TiSapProductPO();
            BeanUtils.copyProperties(sapProductOutDto, productPO);
            productPO.setEffectiveInDatePno12(formatDateYyyy_Mm_dd((sapProductOutDto.getEffectiveInDatePno12())));
            productPO.setEffectiveOutDatePno12(formatDateYyyy_Mm_dd(sapProductOutDto.getEffectiveOutDatePno12()));
            productPO.setEffectiveInDate(formatDateYyyy_Mm_dd(sapProductOutDto.getEffectiveInDate()));
            productPO.setEffectiveOutDate(formatDateYyyy_Mm_dd(sapProductOutDto.getEffectiveOutDate()));
            productPO.setIsHandled(IS_HANDLE_NOT);
            productPO.setBatchNo(batchNo);
            sapProductMapper.insert(productPO);
        }
        for (SapProductRuleOutDto ruleDto : ruleList) {
            TiSapProductRulePO rulePo = new TiSapProductRulePO();
            BeanUtils.copyProperties(ruleDto, rulePo);
            rulePo.setIsHandled(IS_HANDLE_NOT);
            rulePo.setBatchNo(batchNo);
            sapProductRuleMapper.insert(rulePo);
        }
        return;
    }

    public SapOptionInDto getOptionInDto(String param){
        String configCode = null;
        SapOptionInDto sapOptionInDto = null;
        if(StringUtils.isNotEmpty(param)){
            sapOptionInDto = JSONObject.parseObject(param, SapOptionInDto.class);
            if (StringUtils.isEmpty(sapOptionInDto.getPlatForm())){
                sapOptionInDto.setPlatForm(PLATFORM);
            }
        }else{
            sapOptionInDto = new SapOptionInDto();
            sapOptionInDto.setPlatForm(PLATFORM);
        }
        return sapOptionInDto;
    }

    @Override
    public void getOptionInfo(String param) {
        SapOptionInDto sapOptionInDto = getOptionInDto(param);
        String batchNo = UUID.randomUUID().toString();
        RestResultResponse<SapConfigOptionOutDto> res = sapCxfClientService.getOptionRest(batchNo, INTERFACE_OPTION, sapOptionInDto);
        if(res == null || !res.isSuccess()){
           return;
        }
        SapConfigOptionOutDto outDto = res.getData();
        List<SapOptionOutDto> optionList = outDto.getOptionList();
        List<SapConfigPriceDto> priceList = outDto.getPriceList();
        for (SapOptionOutDto sapOptionOutDto : optionList) {
            TiSapOptionPO optionPO = new TiSapOptionPO();
            BeanUtils.copyProperties(sapOptionOutDto, optionPO);
            optionPO.setEffectiveInDate(formatDateYyyy_Mm_dd(sapOptionOutDto.getEffectiveInDate()));
            optionPO.setEffectiveOutDate(formatDateYyyy_Mm_dd(sapOptionOutDto.getEffectiveOutDate()));
            optionPO.setIsHandled(IS_HANDLE_NOT);
            optionPO.setBatchNo(batchNo);
            sapOptionMapper.insert(optionPO);
        }
        if(CollectionUtils.isNotEmpty(priceList)){
            for (SapConfigPriceDto sapConfigPriceDto : priceList) {
                TiSapConfigPricePO pricePO = new TiSapConfigPricePO();
                BeanUtils.copyProperties(sapConfigPriceDto, pricePO);
                pricePO.setIsHandled(IS_HANDLE_NOT);
                pricePO.setBatchNo(batchNo);
                sapConfigPriceMapper.insert(pricePO);
            }
        }
        return;
    }

    @InterfaceLog
    public RestResultResponse<SapConfigOptionOutDto> getOptionRest(String batchNo, String interfaceNo, SapOptionInDto sapOptionInDto){
        RestResultResponse<SapConfigOptionOutDto> res = null;
        try {
            res = sapProductClient.getOptionInfo(sapOptionInDto);
        }catch (Exception e){
            log.error("SAP选装信息获取失败");
        }
        return res;
    }

    public void handleBaseInfoS1(List<TiSapProductPO> handledList){
        Map<String, BrandCacheVO> brandMap = getBrandMap();
        Map<String, SeriesCacheVO> seriesMap = getSeriesMap();
        Map<String, ModelCacheVO> modelMap = getModelMap();
        Map<String, PackageCacheVO> packageMap = getPackageMap();
        Set<String> brandHandledSet = new HashSet<>();
        Set<String> seriesHandledSet = new HashSet<>();
        Set<String> modelHandledSet = new HashSet<>();
        Set<String> packageHandledSet = new HashSet<>();
        Set<String> colorHandledSet = new HashSet<>();
        List<TiSapProductPO> errorList = new ArrayList<>();
        for (TiSapProductPO productPO : handledList) {
            //手动开启事务
            TransactionStatus transaction = transactionUtils.begin(TransactionDefinition.ISOLATION_READ_COMMITTED, TransactionDefinition.PROPAGATION_REQUIRES_NEW);
            try {
                //处理品牌信息
                addOrModifyBrand(productPO, brandMap, brandHandledSet);
                //处理车系信息
                addOrModifySeries(productPO, seriesMap, seriesHandledSet);
                //处理车型信息
                addOrModifyModel(productPO, modelMap, modelHandledSet);
                //处理配置信息
                addOrModifyPackage(productPO, packageMap, packageHandledSet);
                //处理内饰颜色
                addOrModifyColor(productPO.getTrimColorCode(), productPO.getTrimColorName(), BasedataDictConstants.COLOR_TYPE_INNER, colorHandledSet);
                //处理外饰颜色
                addOrModifyColor(productPO.getColorCode(), productPO.getColorName(), BasedataDictConstants.COLOR_TYPE_OUTTER, colorHandledSet);
                transactionUtils.commit(transaction);
            }catch (Exception e){
                errorList.add(productPO);
                log.error("产品数据处理异常{}",JSON.toJSONString(productPO),e);
                transactionUtils.rollback(transaction);
                saveProductExceptionInfo(productPO, e);
                continue;
            }
            //移除异常数据，不再参与下一步
            handledList.removeAll(errorList);
        }
    }

    public void handleProductInfoS2(List<TiSapProductPO> handledList){
        Map<String, BrandCacheVO> brandMap = getBrandMap();
        Map<String, SeriesCacheVO> seriesMap = getSeriesMap();
        Map<String, ModelCacheVO> modelMap = getModelMap();
        Map<String, PackageCacheVO> packageMap = getPackageMap();
        Map<String, ColorCacheVO> colorMap = getColorMap();
        for (TiSapProductPO productPO : handledList) {
            //手动开启事务
            TransactionStatus transaction = transactionUtils.begin(TransactionDefinition.ISOLATION_READ_COMMITTED, TransactionDefinition.PROPAGATION_REQUIRES_NEW);
            try {
                addOrModifyProduct(productPO, brandMap, seriesMap, modelMap, packageMap, colorMap);
                addOrModifyProductOption(productPO);
                productPO.setIsHandled(IS_HANDLE_YES);
                sapProductMapper.updateById(productPO);
                transactionUtils.commit(transaction);
            }catch (Exception e){
                log.error("产品数据处理异常{}",JSON.toJSONString(productPO),e);
                transactionUtils.rollback(transaction);
                saveProductExceptionInfo(productPO, e);
                continue;
            }
        }
    }

    @Override
    public void handleProductInfo(String param) {
        List<TiSapProductPO> handledList = getHandledProdcutInfo(param);
        if(CollectionUtils.isEmpty(handledList)){
            return;
        }
        //处理物料组信息
        handleBaseInfoS1(handledList);
        //处理选装信息
        handleOptionInfo(null);
        //处理物料信息
        handleProductInfoS2(handledList);
    }

    public void addOrModifyBrand(TiSapProductPO productPO, Map<String, BrandCacheVO> brandMap, Set<String> handledSet){
        if(handledSet.contains(productPO.getBrandCode())){
            return;
        }
        String brandCode = productPO.getBrandCode();
        String brandName = productPO.getBrandName();
        BrandModifyDTO brandDto = new BrandModifyDTO();
        brandDto.setBrandCode(brandCode);
        brandDto.setBrandName(brandName);
        brandDto.setIsValid(BasedataDictConstants.IS_VALID);
        brandDto.setIsVehicleSalesBrand(BasedataDictConstants.IS_VALID);
        if(!brandMap.containsKey(brandCode)){
            brandService.addDcsBrand(brandDto);
        }
        handledSet.add(brandCode);
    }

    public void addOrModifySeries(TiSapProductPO productPO, Map<String, SeriesCacheVO> seriesMap, Set<String> handledSet){
        if(handledSet.contains(productPO.getSeriesCode())){
            return;
        }
        String seriesCode = productPO.getSeriesCode();
        String seriesName = productPO.getSeriesName();
        String brandCode = productPO.getBrandCode();
        SeriesModifyDTO seriesDto = new SeriesModifyDTO();
        seriesDto.setSeriesCode(seriesCode);
        seriesDto.setSeriesName(seriesName);
        BrandPO brandPO = brandMapper.selectOne(new LambdaQueryWrapper<BrandPO>().eq(BrandPO::getBrandCode, brandCode));
        seriesDto.setBrandId(brandPO.getBrandId());
        seriesDto.setIsValid(BasedataDictConstants.IS_VALID);
        seriesDto.setPowerType(BasedataDictConstants.POWER_TYPE_ELECTRIC);
        if(!seriesMap.containsKey(seriesCode)){
            seriesService.addDcsSeries(seriesDto);
        }
        handledSet.add(seriesCode);
    }

    public void addOrModifyModel(TiSapProductPO productPO, Map<String, ModelCacheVO> modelMap, Set<String> handledSet){
        if(handledSet.contains(productPO.getModelCode())){
            return;
        }
        String modelCode = productPO.getModelCode();
        String modelName = productPO.getModelName();
        ModelModifyDTO modelDto = new ModelModifyDTO();
        modelDto.setModelCode(modelCode);
        modelDto.setModelName(modelName);
        BrandPO brandPO = brandMapper.selectOne(new LambdaQueryWrapper<BrandPO>().eq(BrandPO::getBrandCode, productPO.getBrandCode()));
        modelDto.setBrandId(brandPO.getBrandId());
        SeriesPO seriesPO = seriesMapper.selectOne(new LambdaQueryWrapper<SeriesPO>().eq(SeriesPO::getSeriesCode, productPO.getSeriesCode()));
        modelDto.setSeriesId(seriesPO.getSeriesId());
        modelDto.setIsValid(BasedataDictConstants.IS_VALID);
        if(!modelMap.containsKey(modelCode)){
            modelService.addDcsModel(modelDto);
        }
        handledSet.add(modelCode);
    }

    public void addOrModifyPackage(TiSapProductPO productPO, Map<String, PackageCacheVO> packageMap, Set<String> handledSet){
        if(handledSet.contains(productPO.getConfigCode())){
            return;
        }
        String configCode = productPO.getConfigCode();
        String configName = productPO.getConfigName();
        PackageModifyDTO packageDto = new PackageModifyDTO();
        packageDto.setConfigCode(configCode);
        packageDto.setConfigName(configName);
        BrandPO brandPO = brandMapper.selectOne(new LambdaQueryWrapper<BrandPO>().eq(BrandPO::getBrandCode, productPO.getBrandCode()));
        packageDto.setBrandId(brandPO.getBrandId());
        SeriesPO seriesPO = seriesMapper.selectOne(new LambdaQueryWrapper<SeriesPO>().eq(SeriesPO::getSeriesCode, productPO.getSeriesCode()));
        packageDto.setSeriesId(seriesPO.getSeriesId());
        ModelPO modelPO = modelMapper.selectOne(new LambdaQueryWrapper<ModelPO>().eq(ModelPO::getModelCode, productPO.getModelCode()));
        packageDto.setModelId(modelPO.getModelId());
        packageDto.setIsValid(BasedataDictConstants.IS_VALID);
        packageDto.setValidStartDate(productPO.getEffectiveInDatePno12());
        packageDto.setValidEndDate(productPO.getEffectiveOutDatePno12());
        if(!packageMap.containsKey(configCode)){
            packageService.addDcsPackage(packageDto);
        }else{
            PackageCacheVO packageCacheVO = packageMap.get(configCode);
            packageDto.setPackageId(packageCacheVO.getPackageId());
            packageService.modifyDcsConfig(packageCacheVO.getPackageId(), packageDto);
        }
        handledSet.add(configCode);
    }

    public void addOrModifyColor(String colorCode, String colorName, Integer colorType, Set<String> handledSet){
        if(handledSet.contains(colorCode)){
            return;
        }
        ColorPO colorPO = colorMapper.selectOne(new LambdaQueryWrapper<ColorPO>().eq(ColorPO::getColorCode, colorCode));
        CarColorDTO colorDto = new CarColorDTO();
        if(colorPO != null){
            colorDto.setColorId(colorPO.getColorId().longValue());
        }
        colorDto.setColorCode(colorCode);
        colorDto.setColorName(colorName);
        colorDto.setColorType(colorType);
        colorDto.setDataSources(BasedataDictConstants.DATA_SOURCES_BY_SUPER);
        colorDto.setIsValid(BasedataDictConstants.IS_VALID);
        if(colorPO != null){
            colorService.updateDcsColor(colorDto.getColorId(), colorDto);
        }else{
            colorService.addDcsColor(colorDto);
        }
        handledSet.add(colorCode);
        return;
    }

    public void addOrModifyProduct(TiSapProductPO po, Map<String, BrandCacheVO> brandMap,
                                    Map<String, SeriesCacheVO> seriesMap, Map<String, ModelCacheVO> modelMap,
                                    Map<String, PackageCacheVO> packageMap, Map<String, ColorCacheVO> colorMap){
        VsProductPO vsProductPo = vsProductMapper.selectOne(new LambdaQueryWrapper<VsProductPO>().eq(VsProductPO::getProductCode, po.getProductCode()));
        SaveProductPriceVO productVo = new SaveProductPriceVO();
        if(vsProductPo != null){
            productVo.setProductId(vsProductPo.getProductId());
        }
        BrandCacheVO brandCacheVo = brandMap.get(po.getBrandCode());
        SeriesCacheVO seriesCacheVo = seriesMap.get(po.getSeriesCode());
        ModelCacheVO modelCacheVo = modelMap.get(po.getModelCode());
        PackageCacheVO packageCacheVo = packageMap.get(po.getConfigCode());
        ColorCacheVO colorCacheVo = colorMap.get(po.getColorCode());
        ColorCacheVO trimColorCacheVo = colorMap.get(po.getTrimColorCode());
        if(brandCacheVo == null || seriesCacheVo == null || modelCacheVo == null || packageCacheVo == null || colorCacheVo == null || trimColorCacheVo == null){
            throw new ServiceBizException("物料数据缺失");
        }

        productVo.setBrandId(brandCacheVo.getBrandId());
        productVo.setSeriesId(seriesCacheVo.getSeriesId());
        productVo.setModelId(modelCacheVo.getModelId());
        productVo.setPackageId(packageCacheVo.getPackageId());
        productVo.setColorId(colorCacheVo.getColorId());
        productVo.setColorCode(po.getColorCode());
        productVo.setColorName(po.getColorName());
        productVo.setTrimColorId(trimColorCacheVo.getColorId());
        productVo.setTrimColor(po.getTrimColorCode());
        productVo.setTrimColorName(po.getTrimColorName());
        productVo.setProductCode(po.getProductCode());
        productVo.setProductName(po.getProductName());
        productVo.setProductStatus(BasedataDictConstants.PRODUCT_STATUS_NORMAL);
        productVo.setEnterDate(po.getEffectiveInDate() == null ? null : po.getEffectiveInDate().toLocalDate().toString());
        productVo.setExeuntDate(po.getEffectiveOutDate() == null ? null: po.getEffectiveOutDate().toLocalDate().toString());
        productVo.setProjectCode(po.getProjectCode());
        productVo.setSalesVersionName(po.getSalesVersionName());
        productVo.setBatteryCode(po.getBatteryCode());
        productVo.setBatteryVolume(po.getBatteryVolume());
        productVo.setBatteryOem(po.getBatteryOem());
        productVo.setPowerCode(po.getPowerCode());
        productVo.setPowerCodeDesc(po.getPowerCodeDesc());
        productVo.setPowerMachineBrand(po.getPowerMachineBrand());
        productVo.setDriveStyleName(po.getDriveStyleName());
        productVo.setYearModelName(po.getYearModelName());
        productVo.setMarketName(po.getMarketName());
        productVo.setOemDirectivePrice(StringUtils.isEmpty(po.getOemDirectivePrice()) ? 0 : Double.valueOf(po.getOemDirectivePrice()));
        vsProductService.saveProductInfoV2(productVo);
    }

    /**
     * 查询该物料当前选装列表和待更新选装列表数据，
     *      循环处理待更新列表，若当前选装列表中存在，则更新数据，并从当前列表移除；不存在，则做新增；
     *      循环结束，当前列表剩余数据为待删除数据
     * @param po
     */
    public void addOrModifyProductOption(TiSapProductPO po){
        String optionCode = po.getOptionCode();
        if(StringUtils.isEmpty(optionCode)) {
            return;
        }
        VsProductPO vsProductPo = vsProductMapper.selectOne(new LambdaQueryWrapper<VsProductPO>().eq(VsProductPO::getProductCode, po.getProductCode()));
        Long productId = vsProductPo.getProductId();
        Long packageId = vsProductPo.getPackageId();
        String[] optionArr = optionCode.split(OPTION_SAPERATOR1);
        //该物料当前选装列表
        List<VsProductOptionPO> currentOptions = vsProductOptionMapper.selectList(new LambdaQueryWrapper<VsProductOptionPO>().eq(VsProductOptionPO::getProductId, productId));
        for (String optionTemp : optionArr) {
//            if(optionTemp.startsWith(OPTION_CODE_EXCLUDE_PRE1)){
//                continue;
//            }
            String option = optionTemp.trim();
            VsOptionPO vsOptionPo = vsOptionMapper.selectOne(new LambdaQueryWrapper<VsOptionPO>().eq(VsOptionPO::getPackageId, packageId)
                    .eq(VsOptionPO::getOptionCode, option));
            if(vsOptionPo == null){
                throw new ServiceBizException("选装["+option+"]未找到");
            }
            //当前选装列表里包含,则不添加，并将选装从当前列表移除
            if(CollectionUtils.isNotEmpty(currentOptions)){
                Optional<VsProductOptionPO> optionResult = currentOptions.stream().filter(t -> vsOptionPo.getOptionId().equals(t.getOptionId())).findAny();
                VsProductOptionPO vsProductOptionPo = optionResult.get();
                currentOptions.remove(vsProductOptionPo);
                vsProductOptionPo.setUpdatedAt(null);
                vsProductOptionMapper.updateById(vsProductOptionPo);
                continue;
            }
            VsProductOptionPO vsProductOptionPO = new VsProductOptionPO();
            vsProductOptionPO.setProductId(productId);
            vsProductOptionPO.setOptionId(vsOptionPo.getOptionId());
            vsProductOptionPO.setAppId(BasedataCommonConstants.APP_ID_RL);
            vsProductOptionPO.setCompanyCode("-1");
            vsProductOptionPO.setOwnerCode("-1");
            vsProductOptionPO.setOwnerParCode("-1");
            vsProductOptionMapper.insert(vsProductOptionPO);
        }
        //未移除的选装，删除
        if(CollectionUtils.isNotEmpty(currentOptions)){
            currentOptions.forEach(t -> {
                vsProductOptionMapper.deleteById(t.getOptionId());
            });
        }
    }


    public Map<String, BrandCacheVO> getBrandMap(){
        Map<String, BrandCacheVO> map = new HashMap<>();
        List<BrandCacheVO> list = brandService.getAllBrandByAppId(BasedataCommonConstants.APP_ID_RL);
        list.forEach(t -> {
            map.put(t.getBrandCode(), t);
        });
        return map;
    }

    public Map<String, SeriesCacheVO> getSeriesMap(){
        Map<String, SeriesCacheVO> map = new HashMap<>();
        List<SeriesCacheVO> list = seriesService.getAllSeriesByAppId(BasedataCommonConstants.APP_ID_RL);
        list.forEach(t -> {
            map.put(t.getSeriesCode(), t);
        });
        return map;
    }

    public Map<String, ModelCacheVO> getModelMap(){
        Map<String, ModelCacheVO> map = new HashMap<>();
        List<ModelCacheVO> list = modelService.getAllModelByAppId(BasedataCommonConstants.APP_ID_RL);
        list.forEach(t -> {
            map.put(t.getModelCode(), t);
        });
        return map;
    }

    public Map<String, PackageCacheVO> getPackageMap(){
        Map<String, PackageCacheVO> map = new HashMap<>();
        List<PackageCacheVO> list = packageService.getAllPackageByAppId(BasedataCommonConstants.APP_ID_RL);
        list.forEach(t -> {
            map.put(t.getConfigCode(), t);
        });
        return map;
    }

    public Map<String, ColorCacheVO> getColorMap(){
        Map<String, ColorCacheVO> map = new HashMap<>();
        List<ColorCacheVO> outterList = colorService.getAllColorByAppIdAndType(BasedataCommonConstants.APP_ID_RL, BasedataDictConstants.COLOR_TYPE_OUTTER);
        List<ColorCacheVO> innerList = colorService.getAllColorByAppIdAndType(BasedataCommonConstants.APP_ID_RL, BasedataDictConstants.COLOR_TYPE_INNER);
        outterList.forEach(t -> {
            map.put(t.getColorCode(), t);
        });
        innerList.forEach(t -> {
            map.put(t.getColorCode(), t);
        });
        return map;
    }

    public Set<String> getProductSet(){
        List<VsProductPO> pos = vsProductMapper.selectList(new LambdaQueryWrapper<VsProductPO>().select(VsProductPO::getProductCode));
        return pos.stream().map(t -> t.getProductCode()).collect(Collectors.toSet());
    }

    public List<TiSapProductPO> getHandledProdcutInfo(String param){
        JSONObject jsonParam = JSON.parseObject(param);
        String ids,batchNo = null;
        LambdaQueryWrapper<TiSapProductPO> qw = new LambdaQueryWrapper<>();
        if(jsonParam == null){
            qw.eq(TiSapProductPO::getIsHandled, IS_HANDLE_NOT);
        }else if(StringUtils.isNotEmpty(ids = jsonParam.getString("ids"))){
            String[] idArray = ids.split(",");
            qw.in(TiSapProductPO::getId, idArray);
        }else if(StringUtils.isNotEmpty(batchNo = jsonParam.getString("batchNo"))){
            qw.eq(TiSapProductPO::getBatchNo, batchNo);
        }else{
            qw.eq(TiSapProductPO::getIsHandled, IS_HANDLE_NOT);
        }
        List<TiSapProductPO> tiSapProductPos = sapProductMapper.selectList(qw);
        return tiSapProductPos;
    }

    @Override
    public void handleOptionInfo(String param) {
        List<TiSapOptionPO> handledList = getHandledOptionInfo(param);
        for (TiSapOptionPO po : handledList) {
            //手动开启事务
            TransactionStatus transaction = transactionUtils.begin(TransactionDefinition.ISOLATION_READ_COMMITTED, TransactionDefinition.PROPAGATION_REQUIRES_NEW);
            try {
                addOrModifyOption(po);
                po.setIsHandled(IS_HANDLE_YES);
                sapOptionMapper.updateById(po);
                transactionUtils.commit(transaction);
            }catch (Exception e){
                log.error("选装数据处理异常{}",JSON.toJSONString(po),e);
                transactionUtils.rollback(transaction);
                saveOptionExceptionInfo(po, e);
                continue;
            }

        }
    }

    @Override
    public void handleConfigPriceInfoJob(String param) {
        List<TiSapConfigPricePO> priceList = getHandledConfigPriceInfo(param);
        List<VsOptionPO> options = vsOptionMapper.selectList(new LambdaQueryWrapper<VsOptionPO>());
        List<ColorPO> colors = colorMapper.selectList(new LambdaQueryWrapper<ColorPO>());
        List<PackagePO> packages = packageMapper.selectList(new LambdaQueryWrapper<PackagePO>());
        Map<String, List<VsOptionPO>> optionMap = options.stream().collect(Collectors.groupingBy(VsOptionPO::getOptionCode));
        Map<String, List<ColorPO>> colorMap = colors.stream().collect(Collectors.groupingBy(ColorPO::getColorCode));
        Map<String, List<PackagePO>> packageMap = packages.stream().collect(Collectors.groupingBy(PackagePO::getConfigCode));
        Set<String> optionSet = optionMap.keySet();
        Set<String> colorSet = colorMap.keySet();
        Set<String> packageSet = packageMap.keySet();
        priceList.forEach(t -> {
            //手动开启事务
            TransactionStatus transaction = transactionUtils.begin(TransactionDefinition.ISOLATION_READ_COMMITTED, TransactionDefinition.PROPAGATION_REQUIRES_NEW);
            try {
                String code = t.getZopitionv();
                if(packageSet.contains(code)){
                    PackagePO po = packageMap.get(code).get(0);
                    po.setIsIssue(BasedataDictConstants.IS_NO_SEND);
                    po.setUpdatedAt(LocalDateTime.now());
                    po.setOemPrice(t.getPrice1());
                    po.setDealerPrice(t.getPrice());
                    packageMapper.updateById(po);
                }else if(colorSet.contains(code)){
                    ColorPO po = colorMap.get(code).get(0);
                    po.setIsIssue(BasedataDictConstants.IS_NO_SEND);
                    po.setUpdatedAt(LocalDateTime.now());
                    po.setOemPrice(t.getPrice1());
                    po.setDealerPrice(t.getPrice());
                    colorMapper.updateById(po);
                }else if(optionSet.contains(code)){
                    List<VsOptionPO> vsOptionPoList = optionMap.get(code);
                    vsOptionPoList.forEach(optionPo -> {
                        optionPo.setIsIssue(BasedataDictConstants.IS_NO_SEND);
                        optionPo.setUpdatedAt(LocalDateTime.now());
                        optionPo.setOemPrice(t.getPrice1());
                        optionPo.setDealerPrice(t.getPrice());
                        vsOptionMapper.updateById(optionPo);
                    });
                }
                t.setIsHandled(IS_HANDLE_YES);
                sapConfigPriceMapper.updateById(t);
                transactionUtils.commit(transaction);
            }catch (Exception e){
                log.error("价格数据处理异常{}",JSON.toJSONString(t),e);
                transactionUtils.rollback(transaction);
                savePriceExceptionInfo(t, e);
                return;
            }

        });
    }

    public List<TiSapConfigPricePO> getHandledConfigPriceInfo(String param) {
        JSONObject jsonParam = JSON.parseObject(param);
        String ids,batchNo = null;
        LambdaQueryWrapper<TiSapConfigPricePO> qw = new LambdaQueryWrapper<>();
        if(jsonParam == null){
            qw.eq(TiSapConfigPricePO::getIsHandled, IS_HANDLE_NOT);
        }else if(StringUtils.isNotEmpty(ids = jsonParam.getString("ids"))){
            String[] idArray = ids.split(",");
            qw.in(TiSapConfigPricePO::getId, idArray);
        }else if(StringUtils.isNotEmpty(batchNo = jsonParam.getString("batchNo"))){
            qw.eq(TiSapConfigPricePO::getBatchNo, batchNo);
        }else{
            qw.eq(TiSapConfigPricePO::getIsHandled, IS_HANDLE_NOT);
        }
        List<TiSapConfigPricePO> priceList = sapConfigPriceMapper.selectList(qw);
        return priceList;
    }

    public void addOrModifyOption(TiSapOptionPO po){
        PackagePO packagePO = packageMapper.selectOne(new LambdaQueryWrapper<PackagePO>().eq(PackagePO::getConfigCode, po.getConfigCode()));
        if(packagePO == null){
            return;
        }
        Long packageId = packagePO.getPackageId();
        List<VsOptionPO> optionRepeatdArray = vsOptionMapper.selectList(new LambdaQueryWrapper<VsOptionPO>().eq(VsOptionPO::getPackageId, packageId)
                .eq(VsOptionPO::getOptionCode, po.getOptionCode()));
        if(CollectionUtils.isNotEmpty(optionRepeatdArray)){
            return;
        }
        ModelPO modelPO = modelMapper.selectById(packagePO.getModelId());
        SeriesPO seriesPO = seriesMapper.selectById(modelPO.getSeriesId());
        BrandPO brandPO = brandMapper.selectById(seriesPO.getBrandId());
        OptionModifyDTO optionDto = new OptionModifyDTO();
        optionDto.setBrandId(brandPO.getBrandId());
        optionDto.setSeriesId(seriesPO.getSeriesId());
        optionDto.setModelId(modelPO.getModelId());
        optionDto.setPackageId(packageId);
        optionDto.setOptionCode(po.getOptionCode());
        optionDto.setOptionName(po.getOptionName());
        optionDto.setIsValid(BasedataDictConstants.IS_VALID);
        optionDto.setDataSources(BasedataDictConstants.DATA_SOURCES_BY_SUPER);
        vsOptionService.addDcsOption(optionDto);
    }

    public List<TiSapOptionPO> getHandledOptionInfo(String param){
        JSONObject jsonParam = JSON.parseObject(param);
        String ids,batchNo = null;
        LambdaQueryWrapper<TiSapOptionPO> qw = new LambdaQueryWrapper<>();
        if(jsonParam == null) {
            qw.eq(TiSapOptionPO::getIsHandled, IS_HANDLE_NOT);
        }else if(StringUtils.isNotEmpty(ids = jsonParam.getString("ids"))){
            String[] idArray = ids.split(",");
            qw.in(TiSapOptionPO::getId, idArray);
        }else if(StringUtils.isNotEmpty(batchNo = jsonParam.getString("batchNo"))){
            qw.eq(TiSapOptionPO::getBatchNo, batchNo);
        }else{
            qw.eq(TiSapOptionPO::getIsHandled, IS_HANDLE_NOT);
        }
        List<TiSapOptionPO> tiSapOptionPos = sapOptionMapper.selectList(qw);
        return tiSapOptionPos;
    }

    public void saveProductExceptionInfo(TiSapProductPO po, Exception e){
        //手动开启事务
        TransactionStatus transaction = transactionUtils.begin(TransactionDefinition.ISOLATION_READ_COMMITTED, TransactionDefinition.PROPAGATION_REQUIRES_NEW);
        try {
            po.setException(ExceptionUtils.getStackTrace(e));
            sapProductMapper.updateById(po);
            transactionUtils.commit(transaction);
        }catch (Exception e1){
            transactionUtils.rollback(transaction);
        }
    }

    public void saveOptionExceptionInfo(TiSapOptionPO po, Exception e){
        //手动开启事务
        TransactionStatus transaction = transactionUtils.begin(TransactionDefinition.ISOLATION_READ_COMMITTED, TransactionDefinition.PROPAGATION_REQUIRES_NEW);
        try {
            po.setException(ExceptionUtils.getStackTrace(e));
            sapOptionMapper.updateById(po);
            transactionUtils.commit(transaction);
        }catch (Exception e1){
            transactionUtils.rollback(transaction);
        }
    }

    public void savePriceExceptionInfo(TiSapConfigPricePO po, Exception e){
        //手动开启事务
        TransactionStatus transaction = transactionUtils.begin(TransactionDefinition.ISOLATION_READ_COMMITTED, TransactionDefinition.PROPAGATION_REQUIRES_NEW);
        try {
            po.setException(ExceptionUtils.getStackTrace(e));
            sapConfigPriceMapper.updateById(po);
            transactionUtils.commit(transaction);
        }catch (Exception e1){
            transactionUtils.rollback(transaction);
        }
    }

    public static  LocalDateTime formatDateYyyy_Mm_dd(String date){
        if(StringUtils.isEmpty(date)){
            return null;
        }
        LocalDate d1 = LocalDate.parse(date);
        return LocalDateTime.of(d1, LocalTime.NOON);
    }


}
